package bch.netty.handler;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;


/**
 * 服务本地存储客户端通道信息,多实例websocket服务, 一个客户端只会连接到一个实例
 * 通道建立在Node1,而发送消息却在Node2就会找不到channel而无法发送消息 , Redis发布订阅模式可以实现跨节点通信
 * 1.socket连接成功。
 * 2.socket消息推送时，把信息发布到redis中。
 * 3.socket服务订阅redis的消息，订阅成功后进行推送。集群下的socket都能订阅到消息，但是只有之前连接成功的节点能推送成功，其余的无法推送。
 * 文本处理器
 *
 * Netty handler的exceptionCaught 只会catch inbound handler的exception, outbound exceptions 需要在writeAndFlush方法里加上listener来监听消息是否发送成功
 *
 * @author DCJ
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class TextWebSocketServerInboundHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) {
        log.info("TextWebSocketServerInboundHandler 收到消息:{}", textWebSocketFrame.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame("【服务器时间】:" + LocalDateTime.now()));
        // 向下传递消息
        // 错误消息发送成功：refCnt: 0, decrement: 1 必须retain计数+1 否则下一个handler无法读取
        ctx.fireChannelRead(textWebSocketFrame.retain());
    }
}
